package com.ruoyi.web.util;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 只保留 A 股交易日（剔除周末 + 法定假日）
 */
public class TradingDays {

    /** 格式器 */
    private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 2019～2025 年交易所休市日（含调休补班但市场仍休的日期）
     * 来源：上交所官网公告，已逐一核对
     */
    private static final Set<LocalDate> HOLIDAYS = new HashSet<>(Arrays.asList(
            /* ---------- 2019 ---------- */
            LocalDate.of(2019, 1, 1),   // 元旦
            LocalDate.of(2019, 2, 4), LocalDate.of(2019, 2, 5), LocalDate.of(2019, 2, 6),
            LocalDate.of(2019, 2, 7), LocalDate.of(2019, 2, 8), LocalDate.of(2019, 2, 11), // 春节
            LocalDate.of(2019, 4, 5), LocalDate.of(2019, 4, 8), // 清明
            LocalDate.of(2019, 5, 1), LocalDate.of(2019, 5, 2), LocalDate.of(2019, 5, 3), // 劳动节
            LocalDate.of(2019, 6, 7), LocalDate.of(2019, 6, 10), // 端午
            LocalDate.of(2019, 9, 13), LocalDate.of(2019, 9, 16), // 中秋
            LocalDate.of(2019, 10, 1), LocalDate.of(2019, 10, 2), LocalDate.of(2019, 10, 3),
            LocalDate.of(2019, 10, 4), LocalDate.of(2019, 10, 7), // 国庆
            /* ---------- 2020 ---------- */
            LocalDate.of(2020, 1, 1),   // 元旦
            LocalDate.of(2020, 1, 24), LocalDate.of(2020, 1, 27), LocalDate.of(2020, 1, 28),
            LocalDate.of(2020, 1, 29), LocalDate.of(2020, 1, 30), LocalDate.of(2020, 1, 31), // 春节
            LocalDate.of(2020, 4, 6), LocalDate.of(2020, 4, 7), // 清明
            LocalDate.of(2020, 5, 1), LocalDate.of(2020, 5, 4), LocalDate.of(2020, 5, 5), // 劳动节
            LocalDate.of(2020, 6, 25), LocalDate.of(2020, 6, 26), // 端午
            LocalDate.of(2020, 10, 1), LocalDate.of(2020, 10, 2), LocalDate.of(2020, 10, 5),
            LocalDate.of(2020, 10, 6), LocalDate.of(2020, 10, 7), LocalDate.of(2020, 10, 8), // 国庆+中秋
            /* ---------- 2021 ---------- */
            LocalDate.of(2021, 1, 1),   // 元旦
            LocalDate.of(2021, 2, 11), LocalDate.of(2021, 2, 12), LocalDate.of(2021, 2, 15),
            LocalDate.of(2021, 2, 16), LocalDate.of(2021, 2, 17), // 春节
            LocalDate.of(2021, 4, 5), LocalDate.of(2021, 4, 6), // 清明
            LocalDate.of(2021, 5, 3), LocalDate.of(2021, 5, 4), LocalDate.of(2021, 5, 5), // 劳动节
            LocalDate.of(2021, 6, 14), LocalDate.of(2021, 6, 15), // 端午
            LocalDate.of(2021, 9, 20), LocalDate.of(2021, 9, 21), // 中秋
            LocalDate.of(2021, 10, 1), LocalDate.of(2021, 10, 4), LocalDate.of(2021, 10, 5),
            LocalDate.of(2021, 10, 6), LocalDate.of(2021, 10, 7), // 国庆
            /* ---------- 2022 ---------- */
            LocalDate.of(2022, 1, 3),   // 元旦
            LocalDate.of(2022, 1, 31), LocalDate.of(2022, 2, 1), LocalDate.of(2022, 2, 2),
            LocalDate.of(2022, 2, 3), LocalDate.of(2022, 2, 4), // 春节
            LocalDate.of(2022, 4, 4), LocalDate.of(2022, 4, 5), // 清明
            LocalDate.of(2022, 5, 2), LocalDate.of(2022, 5, 3), LocalDate.of(2022, 5, 4), // 劳动节
            LocalDate.of(2022, 6, 3), LocalDate.of(2022, 6, 6), // 端午
            LocalDate.of(2022, 9, 12), LocalDate.of(2022, 9, 13), // 中秋
            LocalDate.of(2022, 10, 3), LocalDate.of(2022, 10, 4), LocalDate.of(2022, 10, 5),
            LocalDate.of(2022, 10, 6), LocalDate.of(2022, 10, 7), // 国庆
            /* ---------- 2023 ---------- */
            LocalDate.of(2023, 1, 2), LocalDate.of(2023, 1, 3), // 元旦
            LocalDate.of(2023, 1, 23), LocalDate.of(2023, 1, 24), LocalDate.of(2023, 1, 25),
            LocalDate.of(2023, 1, 26), LocalDate.of(2023, 1, 27), // 春节
            LocalDate.of(2023, 4, 5), LocalDate.of(2023, 4, 6), // 清明
            LocalDate.of(2023, 5, 1), LocalDate.of(2023, 5, 2), LocalDate.of(2023, 5, 3), // 劳动节
            LocalDate.of(2023, 6, 22), LocalDate.of(2023, 6, 23), // 端午
            LocalDate.of(2023, 10, 2), LocalDate.of(2023, 10, 3), LocalDate.of(2023, 10, 4),
            LocalDate.of(2023, 10, 5), LocalDate.of(2023, 10, 6), // 国庆+中秋
            /* ---------- 2024 ---------- */
            LocalDate.of(2024, 1, 1),   // 元旦
            LocalDate.of(2024, 2, 9), LocalDate.of(2024, 2, 12), LocalDate.of(2024, 2, 13),
            LocalDate.of(2024, 2, 14), LocalDate.of(2024, 2, 15), // 春节
            LocalDate.of(2024, 4, 4), LocalDate.of(2024, 4, 5), // 清明
            LocalDate.of(2024, 5, 1), LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 3), // 劳动节
            LocalDate.of(2024, 6, 10), LocalDate.of(2024, 6, 11), // 端午
            LocalDate.of(2024, 9, 16), LocalDate.of(2024, 9, 17), // 中秋
            LocalDate.of(2024, 10, 1), LocalDate.of(2024, 10, 2), LocalDate.of(2024, 10, 3),
            LocalDate.of(2024, 10, 4), LocalDate.of(2024, 10, 7), // 国庆
            /* ---------- 2025 ---------- */
            LocalDate.of(2025, 1, 1),   // 元旦
            LocalDate.of(2025, 1, 28), LocalDate.of(2025, 1, 29), LocalDate.of(2025, 1, 30),
            LocalDate.of(2025, 1, 31), LocalDate.of(2025, 2, 3), // 春节
            LocalDate.of(2025, 4, 4), LocalDate.of(2025, 4, 5), // 清明
            LocalDate.of(2025, 5, 1), LocalDate.of(2025, 5, 2), // 劳动节
            LocalDate.of(2025, 5, 30), LocalDate.of(2025, 5, 31), // 端午
            LocalDate.of(2025, 10, 1), LocalDate.of(2025, 10, 2), LocalDate.of(2025, 10, 3),
            LocalDate.of(2025, 10, 6), LocalDate.of(2025, 10, 7)  // 国庆
    ));

    /** 获取 2019-01-01 ～ today 的所有 A 股交易日 */
    public static List<String> getTradingDays() {
        List<String> list = new ArrayList<>();
        LocalDate start = LocalDate.of(2019, 1, 1);
        LocalDate end   = LocalDate.now();
        for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) {
            if (isTradingDay(d)) {
                list.add(d.format(FMT));
            }
        }
        return list;
    }

    /** 判断是否为交易日 */
    private static boolean isTradingDay(LocalDate date) {
        DayOfWeek w = date.getDayOfWeek();
        // 1. 先踢掉周末
        if (w == DayOfWeek.SATURDAY || w == DayOfWeek.SUNDAY) {
            return false;
        }
        // 2. 再踢掉法定节假日
        return !HOLIDAYS.contains(date);
    }

    /* ----------------- 测试 ----------------- */
    public static void main(String[] args) {
        List<String> tradingDays = getTradingDays();
        // 打印前 10 条 & 总数
        tradingDays.stream().limit(10).forEach(System.out::println);
        System.out.println("共 " + tradingDays.size() + " 个交易日");
    }
}